Week 0: Fundamentals of JavaScript#1
Week 0: Fundamentals of JavaScript#1github-learning-lab[bot] wants to merge 4 commits intomasterfrom
Conversation
|
this is very cool. |
Downloading an IDEFor this assignment, you will follow the instructions and complete a task showing your knowledge of the subject at the end. If at any moment you need help, feel free to contact your TAs. Visual Studio CodeBefore we start coding, we need to install an IDE. An IDE is a software application that provides comprehensive facilities to computer programmers for software development. An IDE normally consists of at least a source code editor, build automation tools, and a debugger. Although there are hundreds of IDEs to choose from, we are going to use Visual Studio Code due to its popularity and integration with Azure (via extensions and libraries). To install VSC, go to: https://code.visualstudio.com/download and choose your operating system (ie. Windows, Mac, Linux, etc). Then click Download and run the installer (usually a .exe or .zip). After it's installed, open it up and try it out. If you need some help navigating VSC, check out this super helpful Youtube video. Make sure to use Dark Theme unless you want to live life on the edge... Task 1: create a JavaScript file that prints out "Hello World" in the terminal. |
|
beau cool. |
Configuring AzureFor this assignment, you will follow the instructions and complete a task showing your knowledge of the subject at the end. If at any moment you need help, feel free to contact your TAs. AzureSo what is "Azure"? Well if you made it into Bit Camp, you really should know already... but according to Microsoft, "Azure is an ever-expanding set of cloud services to help your organization meet your business challenges. It’s the freedom to build, manage, and deploy applications on a massive, global network using your favorite tools and frameworks." If you want to learn more about Azure and all its cloud applications, feel free to check out this link, an overview of its capabilities. To create an Azure account, go to: https://azure.microsoft.com/en-us/free/ and press Start free to be relocated to a signup page. After signing in with your Microsoft account and filling in your personal details, you will be asked to add a credit card. Rest assured, this is only for security purposes (preventing multiple free accounts per person), and you won't be charged unless you choose to buy a premium account, which we do not need for this course. If you need some help navigating Azure, check out this super helpful resource provided by Microsoft. Task 2: create and deploy an HTTP trigger Azure Function that outputs the current time and date. |
|
this course is cool. |
Learning GitHubFor this assignment, you will follow the instructions and complete a task showing your knowledge of the subject at the end. If at any moment you need help, feel free to contact your TAs. GitHubIf you haven't heard of GitHub before, you must have been living under a rock for the past few years. GitHub is a cloud-based repository hosting service that is widely used in the tech industry. It allows teams to use Git for version control, collaboration, and file management. If you don't know what Git is, it's a version-control system for tracking changes, managing state, and concurrently developing on the same files or directories. Git and Github's tools are specifically designed to make coordinating work easier, and they are one of the most pervasive shared tools among students and the industry. If you want to learn more about what it is and how to use it, try taking this GitHub Learning Lab Course. After finishing it, you will have a strong understanding of all the features GitHub has to offer. To make an account, go to: https://github.com/join to sign up. After making an account, you're all set to complete Task 3! Task 3: create a repository and commit a README.md file (make sure you know key functions like commits, forking, pull request, branch, etc). Good job, you're done with all three parts! |
|
scooby doo |
Learning GitHubFor this assignment, you will follow the instructions and complete a task showing your knowledge of the subject at the end. If at any moment you need help, feel free to contact your TAs. GitHubIf you haven't heard of GitHub before, you must have been living under a rock for the past few years. GitHub is a cloud-based repository hosting service that is widely used in the tech industry. It allows teams to use Git for version control, collaboration, and file management. If you don't know what Git is, it's a version-control system for tracking changes, managing state, and concurrently developing on the same files or directories. Git and Github's tools are specifically designed to make coordinating work easier, and they are one of the most pervasive shared tools among students and the industry. If you want to learn more about what it is and how to use it, try taking this GitHub Learning Lab Course. After finishing it, you will have a strong understanding of all the features GitHub has to offer. To make an account, go to: https://github.com/join to sign up. After making an account, you're all set to complete Task 3! Task 3: create a repository and commit a README.md file (make sure you know key functions like commits, forking, pull request, branch, etc). Good job, you're done with all three parts! |
|
scumpy dump |
Create a Face API EndpointThis step is fairly straightforward:
Record and save the API endpoint and subscription key, as we'll be using it in the following parts. |
|
more!? |
Call the Face API P1: Setting ParamsAt this point, your Azure function should look like this: var multipart = require("parse-multipart");
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var boundary = multipart.getBoundary(req.headers['content-type']);
var body = req.body;
var parts = multipart.Parse(body, boundary);
};We're going to create a new function, outside of async function analyzeImage(img){
const subscriptionKey = '<YOUR SUBSCRIPTION KEY>';
const uriBase = '<YOUR ENDPOINT>' + '/face/v1.0/detect';
}Now, we want to set the parameters of our POST request and specify the exact data that we want. The documentation for the Face API is here. Read through it, and notice that the request url is this: https://{endpoint}/face/v1.0/detect[?returnFaceId][&returnFaceLandmarks][&returnFaceAttributes][&recognitionModel][&returnRecognitionModel][&detectionModel] All of the bracketed sections represent possible request parameters. Read through Request Parameters section carefully. How can we specify that we want to get the emotion data? In order to specify all of our parameters easily, we're going to create a new let params = new URLSearchParams({
'returnFaceId': 'true',
'<PARAMETER NAME>': '<PARAMETER VALUE>' //FILL IN THIS LINE
}) |
|
this is unbelievable! |
Call the Face API P2: Using FetchThere are many ways to make a POST request, but to stay consistent, we're going to use the package //install the node-fetch pacakge
var fetch = '<CODE HERE>'Read through the API section of the documentation. Link here. We're going to make a call using the We're calling the For now, fill in the async function analyzeImage(img){
const subscriptionKey = '<YOUR SUBSCRIPTION KEY>';
const uriBase = '<YOUR ENDPOINT>' + '/face/v1.0/detect';
let params = new URLSearchParams({
'returnFaceId': 'true',
'returnFaceAttributes': 'emotion'
})
//COMPLETE THE CODE
let resp = await fetch(uriBase + '?' + params.toString(), {
method: '<METHOD>', //WHAT TYPE OF REQUEST?
body: '<BODY>', //WHAT ARE WE SENDING TO THE API?
headers: {
'<HEADER NAME>': '<HEADER VALUE>' //do this in the next section
}
})
let data = await resp.json();
return data;
}Finally, we have to specify the request headers. Go back the the Face API documentation here, and find the Request headers section. There are two headers that you need. I've provided the format below. Enter in the two header names and their two corresponding values. FYI: The //COMPLETE THE CODE
let resp = await fetch(uriBase + '?' + params.toString(), {
method: '<METHOD>', //WHAT TYPE OF REQUEST?
body: '<BODY>', //WHAT ARE WE SENDING TO THE API?
//ADD YOUR TWO HEADERS HERE
headers: {
'<HEADER NAME>': '<HEADER VALUE>'
}
})Lastly, we want to call the Remember that //module.exports function
//analyze the image
var result = await analyzeImage(parts[0].data);
context.res = {
body: {
result
}
};
console.log(result)
context.done(); |
|
incredible!!!!! |
Call the Face API P2: Using FetchThere are many ways to make a POST request, but to stay consistent, we're going to use the package //install the node-fetch pacakge
var fetch = '<CODE HERE>'Read through the API section of the documentation. Link here. We're going to make a call using the We're calling the For now, fill in the async function analyzeImage(img){
const subscriptionKey = '<YOUR SUBSCRIPTION KEY>';
const uriBase = '<YOUR ENDPOINT>' + '/face/v1.0/detect';
let params = new URLSearchParams({
'returnFaceId': 'true',
'returnFaceAttributes': 'emotion'
})
//COMPLETE THE CODE
let resp = await fetch(uriBase + '?' + params.toString(), {
method: '<METHOD>', //WHAT TYPE OF REQUEST?
body: '<BODY>', //WHAT ARE WE SENDING TO THE API?
headers: {
'<HEADER NAME>': '<HEADER VALUE>' //do this in the next section
}
})
let data = await resp.json();
return data;
}Finally, we have to specify the request headers. Go back the the Face API documentation here, and find the Request headers section. There are two headers that you need. I've provided the format below. Enter in the two header names and their two corresponding values. FYI: The //COMPLETE THE CODE
let resp = await fetch(uriBase + '?' + params.toString(), {
method: '<METHOD>', //WHAT TYPE OF REQUEST?
body: '<BODY>', //WHAT ARE WE SENDING TO THE API?
//ADD YOUR TWO HEADERS HERE
headers: {
'<HEADER NAME>': '<HEADER VALUE>'
}
})Lastly, we want to call the Remember that //module.exports function
//analyze the image
var result = await analyzeImage(parts[0].data);
context.res = {
body: {
result
}
};
console.log(result)
context.done(); |
|
this site is so cool ! |
Creating an HTML PageAfter watching the live demo, you should know the basics of how to create a simple website using the coding language, HTML, and some CSS if you want your webpage to look fancy. Now, your task is to create your own HTML page that inputs an image using a If you still need some help learning HTML and CSS, checkout these resources: W3Schools (HTML): https://www.w3schools.com/html/default.asp W3Schools (CSS): https://www.w3schools.com/css/default.asp Here's a list of HTML items you need to create (please use the id's specified)
Lastly, make sure to reference jQuery: <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="config.js" type="text/javascript"></script>
<script src="song.js" type="text/javascript"></script>
<script src="face.js" type="text/javascript"></script>After that, you're done with the frontend. It's time to use JavaScript! |
|
Youtube.com/Bahburs for fortnite! |
Displaying Emotion Data and Calculating ValenceNow that our image has been analyzed by the Face API, we have received emotion data in JSON format. Our task is to read the JSON file and do two things, output the emotions in the image (ie. anger, contempt, disgust, etc) and convert the emotions to a scale called valence. This is what we are going to use to determine whether we recommend a song that is happy, sad, angry, etc. The first thing we need to do is create a function called var image = //Call for element ID hereWe also need to call for the image source using function loadFile(event) {
var image = //set div for image output
image.src = //Load inputted image
};Now we need to create our main function called
|
|
straightforward is one word contrary to popular belief |
OverviewLogin to Spotify's developer dashboard here. Then press create an app. Give it a cool name and press Create! Click into your app and record the Client Id and Client Secret. Before the actual programming, here's a quick overview of how the project is structured. We're going to be using the revealing module pattern in javascript, which kind of mimics classes in OOP languages like Java. Watch this video, which gives a brief overview of this concept. Let's take a look at an example of a module: Notice that there are parentheses around the function– this indicates that it is an expression and should be evaluated first. So remember: The first set of parentheses evaluate the function. The second set of parentheses call the function. So, the function is essentially declared and run immediately. This is called an IIFE, or immediately invoked function expression. const car = (function(){
var speed = 100;
return {
forward() {
speed += 1;
}
}
})();Notice that because the variable //doesn't work!
car.speed = 101;
//works
car.forward();Also notice that the method //doesn't work
forward();
//works
car.forward();Essentially, just remember that modules:
For more reading, check out this excerpt on the revealing module pattern, as this is not a natural javascript concept if you're new to object-oriented programming. In this project, we're going to have two separate modules that handle distinct concerns– one called To get started, create a new js file called //look at the above example and the APPController declaration for syntax
//both API and UI modules take in no parameters
//spotify api call
const APIController = ??
// UI Module
const UIController = ??
const APPController = (function(UICtrl, APICtrl) {
})(UIController, APIController); |
|
Christianity |
APIControllerThe Inside the APIController module, we're going to write a private method called Use the information in the Authorization Guide (link again) to fill in the necessary fields. Notice also that we've declared variables for the client ID and secret that you received when you registered the app. Hint: use Click for bigger hint:
Read the image!! For syntax:const APIController = (function() {
const clientId = config.CLIENT_ID;
const clientSecret = config.CLIENT_SECRET;
// private methods
const _getToken = async () => {
const result = await fetch('<INSERT CORRECT ENDPOINT>', {
method: '<INSERT CORRECT METHOD>',
headers: {
//content-type: how should the parameters be encoded?
'Content-Type' : '<INSERT CONTENT TYPE>',
//btoa() encodes a string in base64
//what is the string that needs to be encoded?
'Authorization' : 'Basic ' + btoa('<INSERT AUTH STRING>')
},
//what request body parameters are needed?
//the format should be a string, no spaces. ex/ 'parameter_name=value'
body: '<INSERT REQUEST PARAMETERS>'
});
const data = await result.json();
return data.access_token;
}
})();The second private method we need is
Read the documentation for the getting playlist tracks endpoint here. Notice that in the documentation, there are certain Query Parameters that you can add. To add a query parameter, it needs to be in the form of a string like so: //key-value pairs connected by &
const queryString = '{param_1_Name}={param_1_Value}&{param_2_Name}={param_2_Value}'
//then, add your queryString onto the api endpoint with a question mark before
const result = await fetch('{api_endpoint}' + '?' + queryString, {
//blah blah stuff here
})Using the given code, add these things:
Hint: For the headers, there should be one field called Bigger authorization hint: //we specify one field called 'Authorization' and set it to 'Bearer' + token
headers: { 'Authorization' : 'Bearer ' + token}const _getPlaylistItems = async (token, playlistId, limit) => {
//set the query parameter limit to this limit ^ param
const queryString = '<QUERY STRING>'
//hint: the api endpoint should include the playlistId parameter somewhere
//'https://api.spotify.com/v1/playlists/' + playlistId + '/tracks'
const result = await fetch('<API ENDPOINT>' + '?' + queryString, {
method: 'GET',
headers: { '<HEADER_FIELD>' : '<HEADER VALUE>'}
});
const data = await result.json();
return data.items;
} |
|
log |
API Controller P2- Get Recommendations ParamsNow for the most important function in the This function gets song recommendations using this Spotify endpoint. This is a critical resource, so... READ THE WHOLE THING. ALL THE QUERY PARAMETERS
READ THE TUNEABLE TRACK ATTRIBUTES
TRY THE ENDPOINT USING THIS LINK Here's some starting code for At this point you should know that valence is a Tuneable Track Attribute that specifies how happy or sad a song is. Setting a maximum and minimum means that we can only get song recommendations that fit in the range we specify. const _getRecommendations = async(token, seedTracks, limit) => {
console.log('getting recommendations...')
//uses emotion data to set a minimum and max valence
const emotion = document.querySelector('#hiddenemotion').value;
//default values
let minValence = 0;
let maxValence = 1;
//if sad, then range from 0 to 0.33
if (emotion < .33){
maxValence = .33;
}
//if happy, range from .66 to 1
else if (emotion > .66){
minValence = .66;
}
//if neutral, range from .33 to .66
else{
minValence = .33;
maxValence = .66;
}
//make api call below
}Now, we're going to work on the actual api call. Remember how we created a parameter string for our Face API call? let params = new URLSearchParams({
'returnFaceId': 'true',
'<PARAMETER NAME>': '<PARAMETER VALUE>' //FILL IN THIS LINE
})We created a //Create a new URLSearchParams object called params
let params = <CODE HERE>Inside of your search params, specify these parameter-value pairs:
|
|
bdfehjfbsdjhfbjsdhfbdsh |
API Controller P3- Make CallAt this point, your code should look similar to this: //this is the _getRecommendations method inside of your APIController module
const _getRecommendations = async(token, seedTracks, limit) => {
console.log('getting recommendations...')
const emotion = document.querySelector('#hidden-emotion').value;
let minValence = 0;
let maxValence = 1;
if (emotion < .33){
maxValence = .33;
}
else if (emotion > .66){
minValence = .66;
}
else{
minValence = .33;
maxValence = .66;
}
let params = new URLSearchParams({
'min_popularity': '70',
'limit': limit,
'seed_tracks': seedTracks,
'min_valence': minValence,
'max_valence': maxValence
})
//API CALL
}
The last part of the Hint: Look back on your Face API call to see how we can add a parameter string. Click for bigger hint: the actual face api code //FACE API CALL!! notice the '?' and 'params.toString()' !!!
let resp = await fetch(endpoint + '?' + params.toString(), {
//random code
}const result = await fetch('<API ENDPOINT + PARAM STRING>', {
method: 'GET',
headers: { 'Authorization' : 'Bearer ' + token}
});
const data = await result.json();
return data.tracks[0]; |
|
beaubers cool |
API Controller P4- the ReturnHere's the code we have so far for the entire The actual code inside the private methods is hidden for length. Assume that it's there. const APIController = (function() {
const clientId = config.CLIENT_ID;
const clientSecret = config.CLIENT_SECRET;
// private methods
const _getToken = async () => {
//working code
}
const _getPlaylistItems = async (token, playlistId, limit) => {
// cool code
}
const _getRecommendations = async(token, seedTracks, limit) => {
//amazing code
}
})();At this point, everything within the Remember that in the revealing module pattern, we have to explicitly reveal any variables or methods we want to be public. Check out the return statement below. We want to publicly reveal all three of our private methods, and I've done two of them for you. In the return object, I'm creating a new function with the same name but no underscore ( Follow the syntax and to return const APIController = (function() {
const clientId = config.CLIENT_ID;
const clientSecret = config.CLIENT_SECRET;
// private methods
const _getToken = async () => {
// working code
}
const _getPlaylistItems = async (token, playlistId, limit) => {
// cool code
}
const _getRecommendations = async(token, seedTracks, limit) => {
//amazing code
}
//this reveals methods we want to be public
return {
//public method has the same name but no underscore
getToken() {
//inside the method I'm calling the private method and returning the result
return _getToken();
},
getPlaylistItems(token, playlistId, limit) {
return _getPlaylistItems(token, playlistId, limit);
},
//reveal _getRecommendations here with the same syntax
}
})();Once this is done, we can actually call the public methods: //these are all valid calls now
APIController.getToken();
APIController.getPlaylistItems(token, playlistId, limit);
APIController.getRecommendations(token, seedTracks, limit);
// these are still invalid because the methods are private
APIController._getToken();
APIController._getPlaylistItems(token, playlistId, limit);Side note: the return method could also be written like so: return {
getToken: _getToken,
getPlaylistItems: _getPlaylistItems,
getRecommendations: _getRecommendations
}It's quite a bit shorter but doesn't allow you to see the necessary parameters for each function, so I prefer the previous method. That's the completed |
|
bahburs cool |
Create the UIController ModuleYou should already have declared a // UI Module
const UIController = (function() {
})();There isn't a whole lot this module has to do since our app only has to display one song. What we do need to add is a reference to the id of html elements that we will need to alter or listen to during runtime. The two elements are the Find Song button (it has the id Notice that variables //object to hold references to html selectors
const DOMElements = {
button: '#song-button',
divSongDetail: '#song-detail'
}
Two objects to return:
Task: add a line of code at the end of Use the function //public methods
return {
//the inputField is an object containing references to the html fields
inputField: {
songButton: document.querySelector(DOMElements.button),
songDetail: document.querySelector(DOMElements.divSongDetail)
},
// need method to create the song detail
createTrackDetail(img, title, artist) {
const detailDiv = document.querySelector(DOMElements.divSongDetail)
// any time user clicks a new song, we need to clear out the song detail div
detailDiv.innerHTML = '';
const html =
`
<div class="songdisplay">
<img src="${img}" alt="">
<br />
${title}- ${artist}
</div>
`;
//TODO: use the insertAdjacentHTML function here to stick the html string into detailDiv
<CODE HERE>
}
}Note: you could also do this with the And that's it for the UIController! |
|
yuh |
APPControllerYour project should already have an const APPController = (function(UICtrl, APICtrl) {
})(UIController, APIController); //second pair of parentheses need to pass in parameters!Notice that unlike the This also means that the second pair of parentheses need to have the correct parameters- just like a normal function call. So we have to pass in our previously declared modules as parameters. So what does It controls the actual logic of the app and controls when the APICalls are made and the UI input fields are changed. The first thing we need to do is get a reference to the Set the const const APPController = (function(UICtrl, APICtrl) {
// get input field object ref
//hint: u need to use the UICtrl parameter... something like UICtrl.<objectName>
const DOMInputs = <the input field object from UI>
})(UIController, APIController);Next, we need to ensure that pressing the Find Song button will actually call the Spotify API and get a song. This means that we need to add an We have to use the
Let's create the eventListener: Click for hint //DOMInputs is the input field object so to get the button just do:
const buttonElement = DOMInputs.songButton//TODO: create submit button click event listener
const buttonElement = '<set this to the songButton using DOMInputs! >'
//this adds the eventListener
buttonElement.addEventListener('click', async(event) => {
}); |
|
uysadgsadjh |
Event ListenerYour code should look something like this: const APPController = (function(UICtrl, APICtrl) {
// get input field object ref
const DOMInputs = UICtrl.inputField;
// create submit button click event listener
const buttonElement = DOMInputs.songButton;
buttonElement.addEventListener('click', async (event) => {
});
})(UIController, APIController);Let's zoom into the eventListener function. What does it actually need to do?
That's quite a bit of work. Let's go step by step. Step 1: call getToken Hint: remember that we need to reference APICtrl to access getToken! Maybe something like
ALSO!! ALL THE API-RELATED FUNCTIONS ARE ASYNC AND NEED TO BE CALLED WITH THE AWAIT KEYWORD BEFORE soooo... const APPController = (function(UICtrl, APICtrl) {
//get input field object ref
const DOMInputs = UICtrl.inputField;
//create submit button click event listener
const buttonElement = DOMInputs.songButton;
buttonElement.addEventListener('click', async(event) => {
//TODO: call the getToken function using a reference to APICtrl
const token = '<CALL THE FUNCTION HERE>'
});
})(UIController, APIController); Step 2: call const APPController = (function(UICtrl, APICtrl) {
// get input field object ref
const DOMInputs = UICtrl.inputField;
// create submit button click event listener
const buttonElement = DOMInputs.songButton;
buttonElement.addEventListener('click', async(event) => {
const token = '<VALID TOKEN CALL>';
// did this for you- this is the playlist id of Top 50 Hits
const playlistId = "37i9dQZF1DXcBWIGoYBM5M";
// TODO- call getPlaylistItems to get 5 tracks with appropriate params
// REMEMBER TO USE AWAIT!
const tracks = '<CALL THE FUNCTION HERE>';
});
})(UIController, APIController); Step 3: call const APPController = (function(UICtrl, APICtrl) {
// get input field object ref
const DOMInputs = UICtrl.inputField;
// create submit button click event listener
const buttonElement = DOMInputs.songButton;
buttonElement.addEventListener('click', async(event) => {
const token = '<VALID TOKEN CALL>';
const playlistId = "37i9dQZF1DXcBWIGoYBM5M"
const tracks = '<VALID TRACK CALL>';
//seedTracks is declared for you- this is just an array of the IDs of the 5 tracks we just received
let seedTracks = tracks.map(a => a.track.id)
//TODO: call getRecommendations to get 1 track
//USE AWAIT
const recommendedTrack = '<CALL FUNCTION HERE>'
//creating a new trackDetail to display the song
UICtrl.createTrackDetail(recommendedTrack.album.images[2].url,
recommendedTrack.name, recommendedTrack.artists[0].name);
});
})(UIController, APIController); That's it for the APP Controller! In Visual Studio code, install the Live Server extension and run your |
|
jrjksdhfkjsdhfjsd |
|
dhhdhdsh |
|
dhfhsdjkfhksdjfsdjk |
|
hshshahahshshhsdajdhajshdasdsajhdhjas |


Prerequisite: Fundamentals of JavaScript
Welcome to Bit Camp, where students get hands-on experience with software engineering. Before the program starts, please find some time to complete the following assignment: learn/review JavaScript fundamentals that will later be used in the program. To complete this assignment, you will be creating a digital clock using JavaScript to demonstrate your skills! If you need any help, refer to these resources:
W3Schools: https://www.w3schools.com/js/default.asp
Tutorialspoint: https://www.tutorialspoint.com/javascript/javascript_overview.htm
Modern JS: https://javascript.info/
If you have specific questions, try out Stack Overflow (it is super duper helpful):
Stack Overflow: https://stackoverflow.com/
After you have learned/refreshed your knowledge of JavaScript, let's get started on making that clock. Here is the list of the requirements and some extensions you can complete if you have extra time!
Requirements:
Extensions:
Don't know where to get started? Start off by creating a new function that starts your clock:
After this, you will need to create three variables:
Also, make sure to reference the HTML you created the "clock" id in:
Good job, hopefully your digital clock is fully working and your jQuery is linked to our HTML and CSS files. Your next task is a bit more tricky... you're making another clock but this time... in analog mode!
If you have any other questions or need further assistance, feel free to reach out to your TAs!